{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "54bd32c5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-09T06:52:38.038063Z",
     "start_time": "2023-12-09T06:52:37.104554Z"
    },
    "execution": {
     "iopub.execute_input": "2024-01-04T09:20:39.350591Z",
     "iopub.status.busy": "2024-01-04T09:20:39.350112Z",
     "iopub.status.idle": "2024-01-04T09:20:39.999265Z",
     "shell.execute_reply": "2024-01-04T09:20:39.998570Z",
     "shell.execute_reply.started": "2024-01-04T09:20:39.350548Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import scipy.fft as fft\n",
    "import cv2\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "from tqdm import tqdm\n",
    "import pandas as pd\n",
    "from cv2 import dct"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "2f270776",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-09T07:35:19.444806Z",
     "start_time": "2023-12-09T07:35:19.430842Z"
    },
    "execution": {
     "iopub.execute_input": "2024-01-05T06:51:40.192363Z",
     "iopub.status.busy": "2024-01-05T06:51:40.190730Z",
     "iopub.status.idle": "2024-01-05T06:51:40.301263Z",
     "shell.execute_reply": "2024-01-05T06:51:40.300064Z",
     "shell.execute_reply.started": "2024-01-05T06:51:40.192280Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "def image_hash(img_path):\n",
    "    img = processing(img_path)\n",
    "    C_r_list = image_feature(img)\n",
    "    h_i = gen_hashing(C_r_list)\n",
    "    return h_i\n",
    "\n",
    "def processing(img_path):\n",
    "    \"\"\"\n",
    "    input：图片的路径\n",
    "    output：处理后的RGB图片\n",
    "    \"\"\"\n",
    "    img = cv2.imread(img_path)\n",
    "    img = cv2.resize(img, (512,512), interpolation=cv2.INTER_LINEAR)\n",
    "#     out = cv2.GaussianBlur(img, (3, 3),1.3) # 使用python自带的高斯滤波\n",
    "    kernel = np.array([[1,2,1],[2,4,2],[1,2,1]])/16\n",
    "    out = cv2.filter2D(img, -1 , kernel=kernel)  # 二维滤波器\n",
    "    out = cv2.cvtColor(out, cv2.COLOR_BGR2HLS)\n",
    "    return out\n",
    "\n",
    "def image_feature(img):\n",
    "    \"\"\"\n",
    "    iamge:(512,512,3)\n",
    "    return: array格式(x,64,64)\n",
    "    \"\"\"\n",
    "    C_r_list = np.zeros((0,64,64)).tolist()\n",
    "    for i in range(0,512,64):\n",
    "        for j in range(0,512,64):\n",
    "            image_block = img[i:i+64,j:j+64,:]\n",
    "            C_r,C_i,C_j,C_k = QDCT(image_block) # 可以在这里取出实部和三个虚数的实部\n",
    "            C_r_list.append(np.sqrt(C_r**2+C_i**2+C_j**2+C_k**2).tolist())\n",
    "    return np.array(C_r_list)\n",
    "\n",
    "def gen_hashing(feature_matrix):\n",
    "    \"\"\"\n",
    "    生成图像哈希值,和原论文不同，我的P和Q矩阵是每一行代表一个图像块。\n",
    "    input:array (x,64,64)\n",
    "    output:list (x)\n",
    "    \"\"\"\n",
    "    d_i = []\n",
    "    h_i = []\n",
    "    P_matrix = np.zeros((0,32)).tolist()\n",
    "    Q_matrix = np.zeros((0,32)).tolist()\n",
    "    for i in feature_matrix:\n",
    "        i = np.array(i)\n",
    "        row = i[0,1:33].reshape(1,-1)\n",
    "        column = i[1:33,0].reshape(1,-1)\n",
    "        P_matrix.extend(row.tolist())\n",
    "        Q_matrix.extend(column.tolist())\n",
    "    P_matrix = np.array(P_matrix)\n",
    "    Q_matrix = np.array(Q_matrix)\n",
    "    P_matrix_1 = (P_matrix - np.mean(P_matrix,axis = 0))/np.std(P_matrix,axis = 0,ddof=1)\n",
    "    Q_matrix_1 = (Q_matrix - np.mean(Q_matrix,axis = 0))/np.std(Q_matrix,axis = 0,ddof=1)\n",
    "    d_i = np.sqrt(np.sum((P_matrix_1 - Q_matrix_1)**2,axis = 1))\n",
    "    median = np.median(d_i)\n",
    "    for i in d_i:\n",
    "        if i < median:\n",
    "            h_i.append(0)\n",
    "        else:\n",
    "            h_i.append(1)\n",
    "    return np.array(h_i)\n",
    "\n",
    "def QDCT(img):\n",
    "    \"\"\"\n",
    "    img：(64,64,3)\n",
    "    \"\"\"\n",
    "    # C_r = DCT(img[:,:,0]+img[:,:,1]+img[:,:,2]) * (- 1 / np.sqrt(3))\n",
    "    Y = cv2.cvtColor(img, cv2.COLOR_RGB2YUV)[:,:,0]\n",
    "    V_blk = np.sum((Y-np.mean(Y))**2)/(img.shape[0]**2)\n",
    "    C_r = cv2.dct(np.float32(img[:,:,0]+img[:,:,1]+img[:,:,2]) * (- 1 / np.sqrt(3)))\n",
    "    C_i = cv2.dct(np.float32(img[:,:,2]-img[:,:,1]+V_blk) * (1 / np.sqrt(3)))\n",
    "    C_j = cv2.dct(np.float32(img[:,:,0]-img[:,:,2]+V_blk) * (1 / np.sqrt(3)))\n",
    "    C_k = cv2.dct(np.float32(img[:,:,1]-img[:,:,0]+V_blk) * (1 / np.sqrt(3)))\n",
    "    # C_i = DCT(img[:,:,2]-img[:,:,1]) * (1 / np.sqrt(3))\n",
    "    # C_j = DCT(img[:,:,0]-img[:,:,2]) * (1 / np.sqrt(3))\n",
    "    # C_k = DCT(img[:,:,1]-img[:,:,0]) * (1 / np.sqrt(3))\n",
    "    return C_r,C_i,C_j,C_k\n",
    "\n",
    "def DCT(X):\n",
    "    def gen_Matrix(N):\n",
    "        Matrix = np.zeros((N,N),dtype=float)\n",
    "        for row in range(N):#遍历行\n",
    "            if row == 0:#第一行\n",
    "                for col in range(N):\n",
    "                    Matrix[row,col] = 1 / np.sqrt(N)\n",
    "            else:\n",
    "                for col in range(N):\n",
    "                    Matrix[row,col] = np.sqrt(2/N) * (np.cos( (np.pi * (2*col+1) * row) / (2*N)))\n",
    "        return Matrix\n",
    "    Size = list(X.shape)\n",
    "    Rows,Cols = Size[0],Size[1]\n",
    "    A = gen_Matrix(Rows)\n",
    "    B = gen_Matrix(Cols)\n",
    "    B = B.T\n",
    "    T = np.dot(np.dot(A,X),B)\n",
    "    return T\n",
    "    \n",
    "def dist_img(h1,h2):\n",
    "    return sum(np.abs(h1-h2))\n",
    "\n",
    "def dis_different_dir(path):\n",
    "    # 目录下图片之间的距离\n",
    "    dirs = os.listdir(path)\n",
    "    image_set_list = []\n",
    "    image_hashing_value_set = []\n",
    "    for i in tqdm(dirs,ncols = 50):\n",
    "        image_hashing_value_set.append(image_hash(os.path.join(path, i)))\n",
    "    for i in range(len(image_hashing_value_set)):\n",
    "        for j in range(i+1,len(image_hashing_value_set)):\n",
    "            image_set_list.append(dist_img(image_hashing_value_set[i],image_hashing_value_set[j]))\n",
    "    return image_set_list,image_hashing_value_set\n",
    "\n",
    "def dis_similar_dir(path):\n",
    "    # 计算相同类型图片的距离\n",
    "    dir_rotation = os.listdir(path)\n",
    "    dis_similar = []\n",
    "    for i in dir_rotation:\n",
    "        if os.path.splitext(i)[1] == \".bmp\":\n",
    "#             print(os.path.join(path, i)) # 用于查看路径是否有中文\n",
    "            h1 = image_hash(os.path.join(path, i))\n",
    "            dir_temp = os.path.join(path,os.path.splitext(i)[0])\n",
    "            for j in tqdm(os.listdir(dir_temp),ncols = 50):\n",
    "                h2 = image_hash(os.path.join(dir_temp,j))\n",
    "                dis_similar.append(dist_img(h1,h2))\n",
    "    return dis_similar\n",
    "\n",
    "def my_auc(image_similar, image_different):\n",
    "    from scipy import integrate\n",
    "    sum1 = len(image_similar)\n",
    "    sum2 = len(image_different)\n",
    "    tpr = []\n",
    "    fpr = []\n",
    "    threshold_max = (max(max(image_similar), max(image_different)))\n",
    "    for threshold in range(1,threshold_max):\n",
    "        tpr_number = 0\n",
    "        fpr_number = 0\n",
    "        for i in image_similar:\n",
    "            if i < threshold:\n",
    "                tpr_number += 1\n",
    "        for j in image_different:\n",
    "            if j < threshold:\n",
    "                fpr_number += 1\n",
    "        tpr.append(tpr_number/sum1)\n",
    "        fpr.append(fpr_number/sum2)\n",
    "    return integrate.trapezoid(tpr,fpr)\n",
    "\n",
    "def stat_analysis(dir_path):\n",
    "    dirs = os.listdir(dir_path)\n",
    "    for i in dirs:\n",
    "        xlsx_path = os.path.join(dir_path, i)\n",
    "        data = pd.read_excel(xlsx_path,header = 0)[0]\n",
    "        print(f\"{i}的最小值：{min(data)}最大值：{max(data)}平均值：{np.mean(data)}\")\n",
    "\n",
    "def auc_analysis(dir_path):\n",
    "    data_similar_rotation_2 = pd.read_excel(os.path.join(dir_path,\"image_similar_distance_2_标准化.xlsx\"),header = 0)[0]\n",
    "    data_similar_rotation_90 = pd.read_excel(os.path.join(dir_path,\"image_similar_distance_90_标准化.xlsx\"),header = 0)[0]\n",
    "    data_different_set_200 = pd.read_excel(os.path.join(dir_path,\"image_different_distance_200_标准化.xlsx\"),header = 0)[0]\n",
    "    data_different_set_1000 = pd.read_excel(os.path.join(dir_path,\"image_different_distance_1000_标准化.xlsx\"),header = 0)[0]\n",
    "    print(f\"旋转2°和set 200的auc值{my_auc(data_similar_rotation_2,data_different_set_200)}\")\n",
    "    print(f\"旋转2°和set 1000的auc值{my_auc(data_similar_rotation_2,data_different_set_1000)}\")\n",
    "    print(f\"旋转90°和set 200的auc值{my_auc(data_similar_rotation_90,data_different_set_200)}\")\n",
    "    print(f\"旋转90°和set 1000的auc值{my_auc(data_similar_rotation_90,data_different_set_1000)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "280d08c5",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-12-06T03:06:29.525926Z",
     "start_time": "2023-12-06T03:06:29.514955Z"
    },
    "execution": {
     "iopub.execute_input": "2024-01-05T06:51:41.146973Z",
     "iopub.status.busy": "2024-01-05T06:51:41.146546Z",
     "iopub.status.idle": "2024-01-05T06:53:09.886582Z",
     "shell.execute_reply": "2024-01-05T06:53:09.885703Z",
     "shell.execute_reply.started": "2024-01-05T06:51:41.146933Z"
    },
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|█████████████| 57/57 [00:01<00:00, 31.60it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 31.13it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 34.87it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 33.25it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 30.84it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 34.78it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 33.15it/s]\n",
      "100%|█████████████| 57/57 [00:01<00:00, 33.11it/s]\n",
      "100%|█████████████| 44/44 [00:01<00:00, 32.58it/s]\n",
      "100%|█████████████| 16/16 [00:00<00:00, 27.83it/s]\n",
      "100%|█████████████| 44/44 [00:01<00:00, 31.51it/s]\n",
      "100%|█████████████| 16/16 [00:00<00:00, 28.97it/s]\n",
      "100%|█████████████| 44/44 [00:01<00:00, 34.58it/s]\n",
      "100%|█████████████| 16/16 [00:00<00:00, 34.21it/s]\n",
      "100%|█████████████| 44/44 [00:01<00:00, 29.79it/s]\n",
      "100%|█████████████| 16/16 [00:00<00:00, 34.30it/s]\n",
      "100%|█████████████| 44/44 [00:01<00:00, 24.22it/s]\n",
      "100%|█████████████| 16/16 [00:00<00:00, 31.12it/s]\n",
      "100%|███████████| 200/200 [00:08<00:00, 22.77it/s]\n",
      "100%|█████████| 1000/1000 [00:37<00:00, 26.53it/s]\n"
     ]
    }
   ],
   "source": [
    "data_similar_rotation_2 = dis_similar_dir(\"../data/rotation_2/\")\n",
    "pd.DataFrame(data_similar_rotation_2).to_excel(\"./结果/四元数_HLS空间结果/image_similar_distance_2_标准化.xlsx\",index = False)\n",
    "\n",
    "data_similar_rotation_90 = dis_similar_dir(\"../data/rotation_90/\")\n",
    "pd.DataFrame(data_similar_rotation_90).to_excel(\"./结果/四元数_HLS空间结果/image_similar_distance_90_标准化.xlsx\",index = False)\n",
    "\n",
    "data_different_set_200,_ = dis_different_dir(\"../data/Image Set 200/\")\n",
    "pd.DataFrame(data_different_set_200).to_excel(\"./结果/四元数_HLS空间结果/image_different_distance_200_标准化.xlsx\",index = False)\n",
    "\n",
    "data_different_set_1000,_ = dis_different_dir(\"../data/Image Set 1000/\")\n",
    "pd.DataFrame(data_different_set_1000).to_excel(\"./结果/四元数_HLS空间结果/image_different_distance_1000_标准化.xlsx\",index = False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f1f6a015-f8a5-494a-bbf2-d07d1389227c",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-01-05T06:53:10.002976Z",
     "iopub.status.busy": "2024-01-05T06:53:10.002763Z",
     "iopub.status.idle": "2024-01-05T06:53:31.968075Z",
     "shell.execute_reply": "2024-01-05T06:53:31.967122Z",
     "shell.execute_reply.started": "2024-01-05T06:53:10.002955Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "image_similar_distance_2_标准化.xlsx的最小值：0最大值：26平均值：12.394736842105264\n",
      "image_similar_distance_90_标准化.xlsx的最小值：0最大值：42平均值：15.333333333333334\n",
      "image_different_distance_200_标准化.xlsx的最小值：14最大值：50平均值：31.792060301507536\n",
      "image_different_distance_1000_标准化.xlsx的最小值：4最大值：54平均值：31.657825825825824\n",
      "旋转2°和set 200的auc值0.9972869280613594\n",
      "旋转2°和set 1000的auc值0.9967940747765308\n",
      "旋转90°和set 200的auc值0.9336826633165829\n",
      "旋转90°和set 1000的auc值0.932277080413747\n"
     ]
    }
   ],
   "source": [
    "stat_analysis(\"./结果/四元数_HLS空间结果/\")\n",
    "auc_analysis(\"./结果/四元数_HLS空间结果/\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "5ed33d2b-7fd9-4a66-aa4a-dab1b5da2ecf",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-01-04T09:22:15.586007Z",
     "iopub.status.busy": "2024-01-04T09:22:15.585784Z",
     "iopub.status.idle": "2024-01-04T09:22:18.143379Z",
     "shell.execute_reply": "2024-01-04T09:22:18.142550Z",
     "shell.execute_reply.started": "2024-01-04T09:22:15.585976Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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4QXrhx9+sJ566inL39/f+vbbb1u58vbF2+t89913W8uWLbN27dpl7d6927r33nut0NBQ65///GcrV97+eHutz9m/f78VGxtrjRgxwrr99ttbp9h2zNvrXFVVZSUnJ1s333yztW3bNmv//v3Wpk2brLy8vFauvH3x9jq//fbblsPhsN5++21r//791qeffmpFR0dbM2fObOXK25d169ZZc+bMsT744ANLkvXhhx9etH1BQYEVFBRkZWZmWj/88IP18ssvW35+ftb69etbrMYOHUaGDh1qzZgxw/25pqbGiomJsbKysuptP2HCBOuWW27xWJeSkmI98MADLVpne+ftdb7Q2bNnreDgYGvlypUtVWKH0ZxrffbsWWvYsGHWG2+8YU2ePJkw0gTeXudXX33V6tmzp1VdXd1aJXYI3l7nGTNmWL/97W891mVmZlrDhw9v0To7kqaEkccff9zq16+fx7qMjAwrPT29xerqsMM01dXVys3NVVpamnudr6+v0tLSlJOTU+82OTk5Hu0lKT09vcH2aN51vtDJkyd15swZde3ataXK7BCae62feeYZRUZG6r777muNMtu95lznjz/+WKmpqZoxY4acTqf69++vhQsXqqamprXKbneac52HDRum3Nxc91BOQUGB1q1bp5tvvrlVarYLE9+F7eJFec1RWlqqmpoaOZ1Oj/VOp1N79uypd5vi4uJ62xcXF7dYne1dc67zhZ544gnFxMTU+eOHp+Zc623btunNN99UXl5eK1TYMTTnOhcUFGjjxo265557tG7dOu3bt08PPvigzpw5o3nz5rVG2e1Oc67z3XffrdLSUt14442yLEtnz57V9OnT9eSTT7ZGybbR0Hehy+XSqVOn1Llz58t+zA7bM4L2YdGiRVq9erU+/PBDBQYGmi6nQ6moqNDEiRP1+uuvKyIiwnQ5HVptba0iIyP12muvKSkpSRkZGZozZ46WL19uurQOZdOmTVq4cKFeeeUV7dy5Ux988IHWrl2rZ5991nRpuEQdtmckIiJCfn5+Kikp8VhfUlKiqKioereJioryqj2ad53PWbx4sRYtWqT/+7//08CBA1uyzA7B22udn5+vn376SePGjXOvq62tlSR16tRJP/74oxISElq26HaoOX/T0dHR8vf3l5+fn3tdnz59VFxcrOrqagUEBLRoze1Rc67z008/rYkTJ2rq1KmSpAEDBqiyslL333+/5syZI19f/vv6cmjouzAkJKRFekWkDtwzEhAQoKSkJGVnZ7vX1dbWKjs7W6mpqfVuk5qa6tFekjZs2NBgezTvOkvSCy+8oGeffVbr169XcnJya5Ta7nl7rXv37q1vv/1WeXl57uW2227T6NGjlZeXp7i4uNYsv91ozt/08OHDtW/fPnfYk6S9e/cqOjqaINKA5lznkydP1gkc5wKgxWvWLhsj34UtdmtsG7B69WrL4XBYb731lvXDDz9Y999/vxUWFmYVFxdblmVZEydOtGbNmuVu/8UXX1idOnWyFi9ebO3evduaN28ej/Y2gbfXedGiRVZAQID1/vvvW4cPH3YvFRUVpk6h3fD2Wl+Ip2maxtvrfPDgQSs4ONh66KGHrB9//NH65JNPrMjISOu5554zdQrtgrfXed68eVZwcLD13//931ZBQYH12WefWQkJCdaECRNMnUK7UFFRYe3atcvatWuXJclasmSJtWvXLuvAgQOWZVnWrFmzrIkTJ7rbn3u097HHHrN2795tLVu2jEd7L9XLL79sXXXVVVZAQIA1dOhQ66uvvnL/btSoUdbkyZM92r/77rvWtddeawUEBFj9+vWz1q5d28oVt0/eXOerr77aklRnmTdvXusX3g55+zd9PsJI03l7nb/88ksrJSXFcjgcVs+ePa0FCxZYZ8+ebeWq2x9vrvOZM2esf//3f7cSEhKswMBAKy4uznrwwQet48ePt37h7cjnn39e77+5567t5MmTrVGjRtXZZtCgQVZAQIDVs2dP6z//8z9btEYfy6JvCwAAmNNh7xkBAADtA2EEAAAYRRgBAABGEUYAAIBRhBEAAGAUYQQAABhFGAEAAEYRRgAAgFGEEQAAYBRhBAAAGEUYAQAARhFGAACAUf8P+7j8NNulFNUAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.metrics import roc_curve, auc\n",
    "roc_auc = auc(fpr,tpr)   # 准确率代表所有正确的占所有数据的比值\n",
    "plt.plot(fpr, tpr, 'k--', label='ROC (area = {0:.2f})'.format(roc_auc), lw=2)\n",
    "plt.savefig(\"旋转2的roc.png\",dpi=600)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "image",
   "language": "python",
   "name": "image"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
